package graph.dijkstra;

import extra.Position;
import graph.NodeArc;
import graph.NodeWorld;


import interfaces.WorldInterface;
import interfaces.WorldNodeInterface;

import java.awt.List;
import java.awt.Point;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Stack;

import universe.*;




public class PathGraph {

	private NodeWorld rootNode;
	
	private NodeWorld destinyNode;
	
	private LinkedList<NodeWorld> pathList;
	private Stack<NodeWorld> stack;
	private int xScreen;
	private int yScreen;
	
	
	public PathGraph(){
		pathList= new LinkedList<NodeWorld>();
		stack= new Stack<NodeWorld>();
	}
	public PathGraph(NodeWorld node){
		rootNode=node;
		pathList= new LinkedList<NodeWorld>();
		stack= new Stack<NodeWorld>();
	}
	public void generateGraph(Position rootPosition, Position destiny, int depthNumber, WorldInterface world){
		//System.out.println("XACA1: "+destiny.getX()+" YACA1 "+destiny.getY());
		rootNode = world.generateGraph(rootPosition, depthNumber);
		
		destinyNode = new NodeWorld(world.getNode(destiny));
		
		//System.out.println("XACA: "+destinyNode.getObject().getPosition().getX()+" YACA "+destinyNode.getObject().getPosition().getY());
		//System.out.println("XACA1: "+destiny.getX()+" YACA1 "+destiny.getY());
		
		dijkstra();
		
		
	}
	
	public void dijkstra (){
		
		Queue <NodeWorld> queue = new PriorityQueue<NodeWorld>();//<DijkstraNode>();
		pathList= new LinkedList<NodeWorld>();
		//rootNode.setDistance(0);
		queue.add(rootNode);
		
		while(!queue.isEmpty()){
			NodeWorld node = queue.poll();
			
			if(node.getObject()==destinyNode.getObject()){
				destinyNode=node;
				//System.out.println("ENCONTRE MI DESTINY");
			}
			else{
				//System.out.println(" NOLO");
			}
			//System.out.println(" tam "+node.getArcList().size());
			
			pathList.add(node);
			
			Iterator<NodeArc> i = node.getArcList().iterator();
			
			while(i.hasNext()){
				//System.out.println(" eN LOS ARCOS");
				NodeArc arcAux = (NodeArc) i.next();
				NodeWorld nodeAux = (NodeWorld) arcAux.getTarget();
				 
				if(!nodeAux.getObject().isFree()){
					continue;
				}
				if(pathList.contains(nodeAux)){
					//System.out.println("Ya lo tengo");
					continue;
				}
				if(!queue.contains(nodeAux)){
					//nodeAux.setDistance(nodeAux.getDistance()+node.getDistance());
					nodeAux.setAccDistance((int)(arcAux.getDistance()+node.getAccDistance()));
					nodeAux.setSource(node);
					queue.add(nodeAux);
					continue;
				}
				if(nodeAux.getAccDistance()>=node.getAccDistance()+arcAux.getDistance()){
					nodeAux.setAccDistance((int)(node.getAccDistance()+arcAux.getDistance()));
					nodeAux.setSource(node);
				}
				
			}
			
			
		}
		getPathToDestiny();
		
	}
	
	public void getPathToDestiny(){
		
		
		
		if(!pathList.contains(destinyNode)){
			System.out.println("NO PUEDO LLEGAR A ALLA");
			return ;
		}
		
		
		
		
		
		//System.out.println("Node destiny X:"+destinyNode.getBox().getX()+" Y: "+destinyNode.getBox().getY());
		
		
		stack = new Stack<NodeWorld>();
		NodeWorld node = destinyNode;
		
		int i=0;
		while(node.getSource()!=null){
			stack.add(node);
			//System.out.println("Xx: "+node.getBox().getX()+" Yy: "+node.getBox().getY()+" distance: "+node.getDistance());
			node=node.getSource();
			i++;
			
		}
		
		/*if(destinyNode==rootNode && stack.isEmpty()){
			//System.out.println("Ya estoy en el");
			stack.add(new DijkstraNode(new Point(xScreen,yScreen)));
			
		}*/
		
	}
	public Position getPositionToMove(){
		if(stack.isEmpty()){
			return null;
		}
		/*if(stack.size()==1){
			stack.pop();
			return new Point(xScreen,yScreen);
			
		}*/
		return stack.pop().getObject().getMiddlePosition();
	}
	public boolean isEmpty() {
		
		return stack.isEmpty();
	}
	
	
	
/*private Point calculateNewClick(World world, int xClick,int yClick, int xToMove, int yToMove) {
		
		double distance = Integer.MAX_VALUE;
		double distanceAux=Integer.MAX_VALUE;
		int x=0;
		int y=0;
		
		
		System.out.println("xClick "+xClick+" yclick: "+yClick);
		if(xToMove-1>=0){
			if(world.isFree(xToMove-1, yToMove)){
				System.out.println("xComp: "+world.getXScreen(xToMove,yToMove+1)+"yComp: "+world.getYSrceen(xToMove,yToMove+1));
				distance=Math.sqrt(Math.pow((xClick-world.getXScreen(xToMove-1,yToMove)),2)+Math.pow((yClick-world.getYSrceen(xToMove-1,yToMove)),2));
				distanceAux=distance;
				System.out.println("distanciaIzquierda: "+distance);
				x=xToMove-1;
				y=yToMove;
				
			}
			if(yToMove+1<world.getHeight()){
				if(world.isFree(xToMove-1, yToMove+1))
					distanceAux=Math.sqrt(Math.pow((xClick-world.getXScreen(xToMove-1,yToMove+1)),2)+Math.pow((yClick-world.getYSrceen(xToMove-1,yToMove+1)),2));
					if(distanceAux<distance){
						
						distance=distanceAux;
						x=xToMove-1;
						y=yToMove+1;
						System.out.println("distancia Diagonal Izquierda Arriba: "+distance);
						
					}
			}
			if(yToMove-1>=0){
				if(world.isFree(xToMove-1, yToMove-1))
					distanceAux=Math.sqrt(Math.pow((xClick-world.getXScreen(xToMove-1,yToMove-1)),2)+Math.pow((yClick-world.getYSrceen(xToMove-1,yToMove-1)),2));
					if(distanceAux<distance){
						distance=distanceAux;
						x=xToMove-1;
						y=yToMove-1;
						System.out.println("distancia Diagonal Izquierda Abajo: "+distance);
					}
			}
		}
		if(xToMove+1<world.getWidth()){
			if(world.isFree(xToMove+1, yToMove)){
				
				distanceAux=Math.sqrt(Math.pow((xClick-world.getXScreen(xToMove+1,yToMove)),2)+Math.pow((yClick-world.getYSrceen(xToMove+1,yToMove)),2));
				
				if(distanceAux<distance){
					distance=distanceAux;
					x=xToMove+1;
					y=yToMove;
					System.out.println("distanciaDerecha: "+distanceAux);
					
				}
				
			}
			if(yToMove+1<world.getHeight()){
				if(world.isFree(xToMove+1, yToMove+1))
					distanceAux=Math.sqrt(Math.pow((xClick-world.getXScreen(xToMove+1,yToMove+1)),2)+Math.pow((yClick-world.getYSrceen(xToMove+1,yToMove+1)),2));
					if(distanceAux<distance){
						distance=distanceAux;
						x=xToMove+1;
						y=yToMove+1;
						System.out.println("distancia Diagonal Dereccha Abajo: "+distance);
						
					}
			}
			if(yToMove-1>=0){
				if(world.isFree(xToMove+1, yToMove-1))
					distanceAux=Math.sqrt(Math.pow((xClick-world.getXScreen(xToMove+1,yToMove-1)),2)+Math.pow((yClick-world.getYSrceen(xToMove+1,yToMove-1)),2));
					if(distanceAux<distance){
						distance=distanceAux;
						x=xToMove+1;
						y=yToMove-1;
						System.out.println("distancia Diagonal Derecha Arriba: "+distance);
					}
			}
		}
		if(yToMove-1>=0){
			if(world.isFree(xToMove, yToMove-1)){
				
				distanceAux=Math.sqrt(Math.pow((xClick-world.getXScreen(xToMove,yToMove-1)),2)+Math.pow((yClick-world.getYSrceen(xToMove,yToMove-1)),2));
				System.out.println("distanciaArriba: "+distanceAux);
				if(distanceAux<distance){
					distance=distanceAux;
					x=xToMove;
					y=yToMove-1;
					
					
					
				}
			}
		}
		if(yToMove+1<world.getHeight()){
			if(world.isFree(xToMove, yToMove+1)){
				
				distanceAux=Math.sqrt(Math.pow((xClick-world.getXScreen(xToMove,yToMove+1)),2)+Math.pow((yClick-world.getYSrceen(xToMove,yToMove+1)),2));
				System.out.println("distanciaAbajo: "+distanceAux);
				if(distanceAux<distance){
					distance=distanceAux;
					x=xToMove;
					y=yToMove+1;
					
				}
			}
		}
		if(distance!=Integer.MAX_VALUE){
			xToMove=x;
			yToMove=y;
			return new Point(xToMove, yToMove);
			
		}
		return null;
	}
	
	private void calculateClickScreen(int xOld, int yOld,
			int xNew, int yNew) {
		//left
		if(xNew-xOld<0){
			System.out.println("Xscreen "+xScreen);
			xScreen=xNew*Constants.BOX_WIDTH+Constants.BOX_WIDTH;
			System.out.println("Xscreen "+xScreen);
			//yScreen=yClick-Constants.BOX_HEIGHT/2;
			//up
			if(yNew-yOld<0){
				yScreen=yNew*Constants.BOX_HEIGHT+Constants.BOX_HEIGHT;
				//xScreen=xClick-Constants.BOX_WIDTH/2;
				return;
			}
			//down
			if(yNew-yOld>0){
				System.out.println("yscreen "+yScreen);
				yScreen=yNew*Constants.BOX_HEIGHT;
				System.out.println("yscreen "+yScreen);
				//xScreen=xClick-Constants.BOX_WIDTH/2;
				return;
			}
			
			
			return;
		}
		//right
		if(xNew-xOld>0){
			xScreen=xNew*Constants.BOX_WIDTH;//-Constants.BOX_WIDTH/2;
			//yScreen=yClick-Constants.BOX_HEIGHT/2;
			//up
			if(yNew-yOld<0){
				yScreen=yNew*Constants.BOX_HEIGHT+Constants.BOX_HEIGHT;
				//xScreen=xClick-Constants.BOX_WIDTH/2;
				return;
			}
			//down
			if(yNew-yOld>0){
				System.out.println("yscreen "+yScreen);
				yScreen=yNew*Constants.BOX_HEIGHT;
				System.out.println("yscreen "+yScreen);
				//xScreen=xClick-Constants.BOX_WIDTH/2;
				return;
			}
			
			return;
		}
		//up
		if(yNew-yOld<0){
			yScreen=yNew*Constants.BOX_HEIGHT+Constants.BOX_HEIGHT;
			//xScreen=xClick-Constants.BOX_WIDTH/2;
			return;
		}
		//down
		if(yNew-yOld>0){
			System.out.println("yscreen "+yScreen);
			yScreen=yNew*Constants.BOX_HEIGHT;
			System.out.println("yscreen "+yScreen);
			//xScreen=xClick-Constants.BOX_WIDTH/2;
			return;
		}
		
		
	}
	*/
}
